package com.stylefeng.guns.core.aop;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.ReflectUtil;
import com.stylefeng.guns.core.util.JwtTokenUtil;
import com.stylefeng.guns.modular.system.model.UserCw;
import com.stylefeng.guns.modular.system.service.IUserCwService;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/** * @Description 拦截controller update insert 方法 @Author 张亚林 @Date 2018-10-15 */
@Configuration
@Aspect
public class WebControllerAop {
  private static Logger logger = LoggerFactory.getLogger(WebControllerAop.class);

  @Autowired private IUserCwService userCwService;

  @Pointcut("execution(* com.stylefeng.guns.modular.*.controller..*.update*(..))")
  public void updatePointcut() {}

  @Pointcut("execution(* com.stylefeng.guns.modular.*.controller..*.add*(..))")
  public void addPointcut() {}

  @Before("updatePointcut()")
  public void doUpdateBefore(JoinPoint joinPoint) throws Throwable {
    // 获取目标方法的参数信息
    Object[] obj = joinPoint.getArgs();
    // 获取HTTP请求头信息
    RequestAttributes ra = RequestContextHolder.getRequestAttributes();
    ServletRequestAttributes sra = (ServletRequestAttributes) ra;
    HttpServletRequest request = sra.getRequest();
    String token = request.getHeader("Authorization").substring(7);
    String subject = JwtTokenUtil.getClaimFromToken(token).getSubject(); // 用户ID
    UserCw userCw = null;
    if (StringUtils.isNotEmpty(subject)) {
      userCw = this.userCwService.selectById(subject);
    }

    for (Object argItem : obj) {
      System.out.println("---->now-->argItem:" + argItem);
      // BeanUtil.isBean方法根据是否存在只有一个参数的setXXX方法来判定是否是一个Bean对象。这样的判定方法主要目的是保证至少有一个setXXX方法用于属性注入。
      boolean isBean = BeanUtil.isBean(argItem.getClass());
      if (isBean) {
        Method method = ReflectUtil.getMethod(argItem.getClass(), "getUpdateUser");
        if (method != null) {
          Map<String, Object> map = new HashMap<>();
          map.put("updateTime", DateTime.now());
          map.put("updateUser", userCw.getSuId());
          // 将Map注入Bean
          BeanUtil.fillBeanWithMap(map, argItem, true);
        }
      }
      System.out.println("---->after-->argItem:" + argItem);
    }
  }

  @Before("addPointcut()")
  public void doAddBefore(JoinPoint joinPoint) throws Throwable {
    System.out.println("我是前置通知，我将要执行一个Add方法了");
    // 获取目标方法的参数信息
    Object[] obj = joinPoint.getArgs();
    // 获取HTTP请求头信息
    RequestAttributes ra = RequestContextHolder.getRequestAttributes();
    ServletRequestAttributes sra = (ServletRequestAttributes) ra;
    HttpServletRequest request = sra.getRequest();
    String token = request.getHeader("Authorization").substring(7);
    String subject = JwtTokenUtil.getClaimFromToken(token).getSubject(); // 用户ID
    UserCw userCw = null;
    if (StringUtils.isNotEmpty(subject)) {
      userCw = this.userCwService.selectById(subject);
    }
    for (Object argItem : obj) {
      System.out.println("---->now-->argItem:" + argItem);
      boolean isBean = BeanUtil.isBean(argItem.getClass());
      if (isBean) {
        Method method = ReflectUtil.getMethod(argItem.getClass(), "getCreateUser");
        if (method != null) {
          Map<String, Object> map = new HashMap<>();
          map.put("createTime", DateTime.now());
          map.put("createUser", userCw.getSuId());
          // 将Map注入Bean
          BeanUtil.fillBeanWithMap(map, argItem, true);
        }
      }
      System.out.println("---->after-->argItem:" + argItem);
    }
  }
}
